﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using TheMovieDB;
using System.Net;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Reflection;

namespace MovieDB
{
    /// <summary>
    /// Helferfunktionen, die sowohl vom Hauptprogramm, als auch von Plugins genutzt werden können
    /// </summary>
    public static class MdbUtils
    {
        /// <summary>
        /// Gibt eine XmlDocument Struktur zurück, die Filminfos bereithält
        /// </summary>
        /// <param name="movie">TmdbMovie element, dessen Informationen ausgewertet werden sollen</param>
        /// <returns></returns>
        public static XmlDocument CreateMovieXml(TmdbMovie movie)
        {
            XmlDocument doc = new XmlDocument();
            XmlNode root, node, subNode;

            root = doc.CreateElement("movie");

            node = doc.CreateElement("title");
            node.InnerText = movie.Name;
            root.AppendChild(node);

            node = doc.CreateElement("rating");
            node.InnerText = movie.Rating.ToString();
            root.AppendChild(node);

            node = doc.CreateElement("year");
            node.InnerText = ((DateTime)movie.Released).Year.ToString();
            root.AppendChild(node);

            node = doc.CreateElement("plot");
            node.InnerText = movie.Overview;
            root.AppendChild(node);

            node = doc.CreateElement("runtime");
            node.InnerText = movie.Runtime.ToString();
            root.AppendChild(node);

            node = doc.CreateElement("id");
            node.InnerText = movie.ImdbId;
            root.AppendChild(node);

            if (movie.Categories != null && movie.Categories.Length > 0)
            {
                node = doc.CreateElement("genre");
                node.InnerText = movie.Categories[0].Name;
                for (int i = 1; i < movie.Categories.Length - 1; i++)
                {
                    node.InnerText += " / " + movie.Categories[i];
                }
                root.AppendChild(node);
            }

            if (movie.Studios != null && movie.Studios.Length > 0)
            {
                node = doc.CreateElement("studio");
                node.InnerText = movie.Studios[0].Name;
                for (int i = 1; i < movie.Studios.Length - 1; i++)
                {
                    node.InnerText += " / " + movie.Studios[i];
                }
                root.AppendChild(node);
            }

            if (movie.Cast != null)
            {
                foreach (TmdbCastPerson person in movie.Cast)
                {
                    node = doc.CreateElement("actor");

                    subNode = doc.CreateElement("name");
                    subNode.InnerText = person.Name;
                    node.AppendChild(subNode);

                    subNode = doc.CreateElement("role");
                    subNode.InnerText = person.Character;
                    node.AppendChild(subNode);

                    root.AppendChild(node);
                }
            }

            doc.AppendChild(root);

            return doc;
        }

        /// <summary>
        /// Speichert das größte Bild der Collection das vom angegebenen Typ ist im Verzeichnis des Films
        /// Zusätzlich werden alle gefundenen Bilder in der Datenbank abgespeichert, falls sie dort noch nicht vorhanden sind
        /// </summary>
        /// <param name="movie">Der Film</param>
        /// <param name="type">Der Typ des Bildes, das abgespeichert werden soll</param>
        /// <param name="fileName">Dateiname des Bildes im Filmverzeichnis</param>
        /// <param name="dbDirectory">Pfad zum Datenbankverzeichnis</param>
        public static void SaveImage(MdbMovie movie, TmdbImageType type, string fileName, string dbDirectory)
        {
            int tmpWidth = 0;
            Image imgSave = null;

            foreach (TmdbImage img in movie.Current.Images)
            {
                if (img.Type == type)
                {
                    Image imgTemp = null;
                    string dbFileName = dbDirectory + "\\" + movie.Current.ImdbId + "\\images\\";
                    if (type == TmdbImageType.backdrop)
                    {
                        dbFileName += "Backdrop\\" + img.Url.Substring(img.Url.LastIndexOf("/") + 1);

                        if (!Directory.Exists(dbDirectory + "\\" + movie.Current.ImdbId + "\\images\\Backdrop"))
                        {
                            Directory.CreateDirectory(dbDirectory + "\\" + movie.Current.ImdbId + "\\images\\Backdrop");
                        }
                    }
                    else if (type == TmdbImageType.poster)
                    {
                        dbFileName += "Poster\\" + img.Url.Substring(img.Url.LastIndexOf("/") + 1);

                        if (!Directory.Exists(dbDirectory + "\\" + movie.Current.ImdbId + "\\images\\Poster"))
                        {
                            Directory.CreateDirectory(dbDirectory + "\\" + movie.Current.ImdbId + "\\images\\Poster");
                        }
                    }

                    
                    if (!File.Exists(dbFileName))
                    {
                        try
                        {
                            WebRequest requestPic = WebRequest.Create(img.Url);
                            WebResponse responsePic = requestPic.GetResponse();
                            FileStream fs = new FileStream(dbFileName, FileMode.Create);
                            imgTemp = Image.FromStream(responsePic.GetResponseStream());
                            imgTemp.Save(fs, ImageFormat.Jpeg);
                            fs.Close();
                        }
                        catch (WebException e)
                        {
                            MessageBox.Show("Fehler: " + e.Message);
                        }
                    }
                    else
                    {
                        try
                        {
                            FileStream fs = new FileStream(dbFileName, FileMode.Open);
                            imgTemp = Image.FromStream(fs);
                            fs.Close();
                        }
                        catch (Exception e)
                        {
                            imgTemp = Image.FromFile(dbFileName);
                        }
                    }
                    if (imgTemp != null)
                    {
                        if (img.Width > tmpWidth)
                        {
                            imgSave = new Bitmap(imgTemp);
                            tmpWidth = img.Width;
                        }


                        imgTemp.Dispose();
                    }
                }
            }

            if (imgSave != null)
            {
                FileStream fs = new FileStream(movie.Path + @"\" + fileName, FileMode.Create);
                imgSave.Save(fs, ImageFormat.Jpeg);
                fs.Close();
            }
        }

        /// <summary>
        /// Die Methode liest alle Plugins in einem Verzeichnis ein
        /// </summary>
        /// <param name="directory">Das Verzeichnis, in dem gesucht werden soll</param>
        /// <returns>Liste von IPlugin Objekten</returns>
        public static List<IPlugin> GetMovieDbPlugins(string directory)
        {
            List<IPlugin> list = new List<IPlugin>();

            // Laden der Plugins
            if (Directory.Exists(directory))
            {
                foreach (string plugin in Directory.GetFiles(directory))
                {
                    Assembly asm = Assembly.LoadFrom(plugin);
                    Type typ = asm.GetType("MovieDB.MdbConnect");
                    IPlugin plug;

                    if (typ != null)
                    {
                        MethodInfo mi = typ.GetMethod("GetPlugInObject");
                        if (mi != null)
                        {
                            plug = (IPlugin)mi.Invoke(null, null);
                            list.Add(plug);
                        }
                    }
                    else
                    {
                        MessageBox.Show("Fehler beim Laden des PlugIns " + plugin);
                    }
                }
            }

            return list;
        }

        /// <summary>
        /// Liest alle Filme in einem Verzeichnis ein
        /// </summary>
        /// <param name="directory">Das Verzeichnis, in dem gesucht werden soll</param>
        /// <param name="tmdb">TmdbApi objekt um die Verbindung herzustellen</param>
        /// <returns>Liste von MdbMovie Objekten</returns>
        public static List<MdbMovie> ScanDirForMovies(string directory, TmdbAPI tmdb)
        {
            List<MdbMovie> list = new List<MdbMovie>();

            if (Directory.Exists(directory))
            {
                // Alle Filmordner einlesen
                foreach (string dir in Directory.GetDirectories(directory))
                {
                    MdbMovie movie = new MdbMovie(dir, tmdb);              

                    list.Add(movie);
                }
            }

            return list;
        }
    }
}
